package org.light.simpleauth;

import java.util.ArrayList;
import java.util.List;

import org.light.core.Writeable;
import org.light.domain.Domain;
import org.light.domain.Statement;
import org.light.domain.StatementList;
import org.light.generator.Generator;
import org.light.utils.RandomUtil;
import org.light.utils.StringUtil;
import org.light.utils.WriteableUtil;

public class LoginMiddlewareGenerator extends Generator{
	protected Domain userDomain;

	public Domain getUserDomain() {
		return userDomain;
	}

	public void setUserDomain(Domain userDomain) {
		this.userDomain = userDomain;
	}

	public LoginMiddlewareGenerator(){
		super();
		super.fileName = "login_middleware.rs";
		super.standardName = "LoginMiddleware";
	}

	@Override
	public StatementList generateStatementList() {
		List<Writeable> sList = new ArrayList<Writeable>();

		sList.add(new Statement(1000L,0,"use axum::{"));
		sList.add(new Statement(2000L,1,"body::{Bytes, HttpBody},"));
		sList.add(new Statement(3000L,1,"headers::HeaderMap,"));
		sList.add(new Statement(4000L,1,"http::{HeaderValue, Request},"));
		sList.add(new Statement(5000L,1,"middleware::{self, Next},"));
		sList.add(new Statement(6000L,1,"response::{IntoResponse,Response,Redirect},"));
		sList.add(new Statement(7000L,1,"routing::get,"));
		sList.add(new Statement(8000L,1,"Router,"));
		sList.add(new Statement(9000L,1,"extract::OriginalUri,"));
		sList.add(new Statement(10000L,0,"};"));
		sList.add(new Statement(11000L,0,""));
		sList.add(new Statement(12000L,0,"use crate::"+this.userDomain.getServiceimplSuffix()+"::login_service::{can_access};"));
		sList.add(new Statement(13000L,0,"use std::str::FromStr;"));
		sList.add(new Statement(14000L,0,""));
		sList.add(new Statement(15000L,0,"use axum_sessions::{"));
		sList.add(new Statement(16000L,1,"async_session::MemoryStore, extractors::WritableSession, PersistencePolicy, SessionLayer,"));
		sList.add(new Statement(17000L,0,"};"));
		sList.add(new Statement(18000L,0,"use axum_sessions::SessionHandle;"));
		sList.add(new Statement(19000L,0,"use axum_sessions::Session;"));
		sList.add(new Statement(20000L,0,""));
		sList.add(new Statement(21000L,0,"pub async fn check_auth<B>(req:Request<B>, next:Next<B>) -> Response"));
		sList.add(new Statement(22000L,0,"where"));
		sList.add(new Statement(23000L,1,"B:std::fmt::Debug,"));
		sList.add(new Statement(24000L,0,"{"));
		sList.add(new Statement(25000L,1,"let uri = req.uri().clone().to_string();"));
		sList.add(new Statement(26000L,1,"let mut token = \"\".to_string();"));
		sList.add(new Statement(27000L,1,"let mut can_access_bool  = can_access(\"\".to_string(),uri.clone()).await;;"));
		sList.add(new Statement(28000L,1,"println!(\"{}\",uri.clone());"));
		sList.add(new Statement(29000L,1,"if can_access_bool == false {"));
		sList.add(new Statement(30000L,2,"let session_handle = req.extensions().get::<SessionHandle>().unwrap();"));
		sList.add(new Statement(31000L,2,""));
		sList.add(new Statement(32000L,2,"let session = session_handle.read().await;"));
		sList.add(new Statement(33000L,2,"let stoken = session.get(\"token\");"));
		sList.add(new Statement(34000L,0,""));
		sList.add(new Statement(35000L,2,"match stoken {"));
		sList.add(new Statement(36000L,3,"Some(stoken) => {"));
		sList.add(new Statement(37000L,4,"token = stoken;"));
		sList.add(new Statement(38000L,3,"},"));
		sList.add(new Statement(39000L,3,"None => {"));
		sList.add(new Statement(40000L,4,"let headers = req.headers();"));
		sList.add(new Statement(41000L,4,"token = headers.get(\"X-Token\").unwrap().to_str().unwrap().to_string();"));
		sList.add(new Statement(42000L,3,"}"));
		sList.add(new Statement(43000L,2,"}"));
		sList.add(new Statement(44000L,2,"println!("));
		sList.add(new Statement(45000L,2,"\"before x-token: {}\","));
		sList.add(new Statement(46000L,2,"token"));
		sList.add(new Statement(47000L,2,");"));
		sList.add(new Statement(48000L,2,"can_access_bool = can_access(token,uri).await;"));
		sList.add(new Statement(49000L,2,"println!(\"{}\",can_access_bool);"));
		sList.add(new Statement(50000L,1,""));
		sList.add(new Statement(51000L,1,"}"));
		sList.add(new Statement(52000L,0,""));
		sList.add(new Statement(53000L,1,"if can_access_bool {"));
		sList.add(new Statement(54000L,2,"let response = next.run(req).await;"));
		sList.add(new Statement(55000L,2,"return response;"));
		sList.add(new Statement(56000L,1,"}"));
		sList.add(new Statement(57000L,1,"r#\"{  \"rows\": null,  \"success\": false, \"noAuth\":true}\"#.into_response()"));
		sList.add(new Statement(58000L,0,"}"));
		sList.add(new Statement(59000L,0,""));
		sList.add(new Statement(60000L,0,""));
		sList.add(new Statement(61000L,0,"async fn body_into_text<B>(body: B) -> String"));
		sList.add(new Statement(62000L,0,"where"));
		sList.add(new Statement(63000L,1,"B: HttpBody<Data = Bytes> + Unpin,"));
		sList.add(new Statement(64000L,1,"B::Error: std::fmt::Debug,"));
		sList.add(new Statement(65000L,0,"{"));
		sList.add(new Statement(66000L,1,"let bytes = hyper::body::to_bytes(body).await.unwrap();"));
		sList.add(new Statement(67000L,1,"String::from_utf8(bytes.to_vec()).unwrap()"));
		sList.add(new Statement(68000L,0,"}"));
		sList.add(new Statement(69000L,0,""));
		sList.add(new Statement(70000L,0,"fn get_header_value_or_empty(headers: &HeaderMap, key: &str) -> String {"));
		sList.add(new Statement(71000L,1,"headers"));
		sList.add(new Statement(72000L,2,".get(key)"));
		sList.add(new Statement(73000L,2,".map(|x| x.to_owned())"));
		sList.add(new Statement(74000L,2,".unwrap_or(HeaderValue::from_static(\"\"))"));
		sList.add(new Statement(75000L,2,".to_str()"));
		sList.add(new Statement(76000L,2,".unwrap()"));
		sList.add(new Statement(77000L,2,".to_owned()"));
		sList.add(new Statement(78000L,0,"}"));

		return WriteableUtil.merge(sList);
	}

}
